#pragma once 
#include "Reactor.hpp"
#include "Util.hpp"
#include <cerrno>
#include <string>
#include <vector>

#define READ_SIZE 128

//1、本轮读取全部完成 0、对端关闭连接 -1、读取出错
static int RecverCore(int sock, std::string &inbuffer){
    while (true){
        char buffer[READ_SIZE];
        ssize_t s = recv(sock, buffer, READ_SIZE, 0);
        if (s > 0){
            // 读取成功
            buffer[s] = '\0';
            inbuffer += buffer;
        }
        else if (s < 0) {
            if (errno == EINTR){
                // IO 被信号打断了，概率非常低
                continue;
            }
            if (errno == EAGAIN || errno == EWOULDBLOCK){
                return 1; // 读完了，底层没数据了
            }
            return -1;
        }
        else {
            return 0;     //对方将连接关闭了
        }
    }
}

int Recver(Event *evp){
    std::cout << "Recv Callback has been called!" << std::endl;
    // 1.真正的读取网络数据
    int result = RecverCore(evp->sock, evp->inbuffer);
    if (result <= 0) {
        // 差错处理
        if (evp->errorer) evp->errorer(evp);
        return -1;
    }
    // 2.分包 只会读取完整报文 --解决粘包问题
    std::vector<std::string> tokens;
    SplitSegment(evp->inbuffer, &tokens, "X");
    std::string sep = "X";
    // 3.反序列化 --针对一个报文，提取有效参与计算或者存储信息
    for (auto& seg : tokens){
        std::string data1, data2;
        // 和业务强相关
        if (Deserialize(seg, &data1, &data2)){
            // 4.业务逻辑 --得到结果
            int x = atoi(data1.c_str());
            int y = atoi(data2.c_str());
            int z = x + y;
            // 5.构建响应 -- 并将响应添加到evp->outbuffer
            std::string res = data1;
            res += "+";
            res += data2;
            res += "=";
            res += std::to_string(z);
            res += sep;
            evp->outbuffer += res; //发送数据
            
        }    
    }
    // 6.尝试进行直接或者间接发送
    // 写事件一般都是就绪的，但是用户不一定是就绪的，对于写事件通常都是按需设置
    if (!evp->outbuffer.empty()){
        // 写打开的时候，默认就是就绪的！即便是发送缓冲区已经满了
        // epoll 规定只要用户重新设置了OUT事件，EPOLLOUT至少会在触发一次
        evp->R->EnableReadWriter(evp->sock, true, true);
    }
}

// 1.数据全部发送完成 0.数据还没有发完，但是只能下次再发了 -1、发送失败
static int SenderCore(int sock, std::string &outbuffer){
    while (true){
        int total = 0; //累计发送的数据量
        const char *start = outbuffer.c_str();
        int size = outbuffer.size();   // 缓冲区发送的总大小
        ssize_t curr = send(sock, start + total, size - total, 0);
        if (curr > 0){
            total += curr;
            if (total == size){
                // 将数据全部发送完成
                outbuffer.clear();
                return 1;
            }
        }
        else {
            // 数据没有发完，但是不能再发了
            if (errno == EINTR) continue;
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                outbuffer.erase(0, total);
                return 0;
            }
            return -1;
        }
    }
}

int Sender(Event *evp){
    std::cout << "Sender been called" << std::endl;
    int result = SenderCore(evp->sock, evp->outbuffer);
    if (result == 1){
        evp->R->EnableReadWriter(evp->sock, true, false);
    }
    else if (result == 0){
        evp->R->EnableReadWriter(evp->sock, true, true);
    }
    else {
        if (evp->errorer){
            evp->errorer;
        }
    }
    return 0;
}

int Errorer(Event *evp){
    std::cout << "Errorer been called" << std::endl;
    evp->R->DeleteEvent(evp);
}